import os
import socket
import select
import pickle
import struct
import time

from time import struct_time

CMD_NONE = 1
CMD_LOGIN = 2
CMD_LOGOUT = 3

class CPackageHead(object):
    def __init__(self, iLen):
        self.m_PackageLength = iLen

class CPackage(object):
    def __init__(self, data):
        self.m_Data = data

class CClientSocket(object):
    def __init__(self, oSocket):
        self.m_Socket = oSocket
        self.m_MsgBuf = b""
        self.m_SocketLen = 0

    def RecvMsg(self):
        while True:
            if self.m_SocketLen == 0:
                try:
                    self.m_MsgBuf += self.m_Socket.recv(4)
                except:
                    break
                if len(self.m_MsgBuf) >= 4:
                    sLen = self.m_MsgBuf[:4]
                    self.m_MsgBuf = self.m_MsgBuf[4:]
                    iLen = struct.unpack("i", sLen)[0]
                    self.m_SocketLen = iLen
                else:
                    break
            else:
                try:
                    self.m_MsgBuf += self.m_Socket.recv(self.m_SocketLen)
                except:
                    break
                if len(self.m_MsgBuf) >= self.m_SocketLen:
                    sMsg = self.m_MsgBuf[:self.m_SocketLen]
                    self.m_MsgBuf = self.m_MsgBuf[self.m_SocketLen:]
                    self.m_SocketLen = 0
                    oPackage = pickle.loads(sMsg)
                    GetNetWorkManager().AddPackage(self.m_Socket.fileno(), oPackage)
                else:
                    break

class CNetWorkManager(object):
    def __init__(self):
        self.m_PackageList =[]
        self.m_SendPackageList = []
        self.m_ServerSocket = None
        self.m_ClientSocketInfo = {}
    
    def AddPackage(self, iFileNo, oPackage):
        self.m_PackageList.append((iFileNo, oPackage))

    def PopPackage(self):
        if self.m_PackageList:
            return self.m_PackageList.pop(0)
        else:
            return None
    
    def PopAllPackage(self):
        lstPacket = self.m_PackageList
        self.m_PackageList = []
        return lstPacket

    def SendMsg(self, fid, sMsg):
        self.m_SendPackageList.append((fid, sMsg))
    
    def SendAll(self, sMsg):
        self.m_SendPackageList.append((0, sMsg))

    def StartListen(self):
        self.m_ServerSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.m_ServerSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.m_ServerSocket.bind(("127.0.0.1", 9003))
        self.m_ServerSocket.listen(10)
        self.m_ServerSocket.setblocking(False)

        iTimeOut = 5
        oEpoll = select.epoll()
        oEpoll.register(self.m_ServerSocket.fileno(), select.EPOLLIN)
        self.EpollLoop(oEpoll)

    def SendLoop(self):
        while True:
            lstSend = self.m_SendPackageList
            self.m_SendPackageList = []
            for fid, sMsg in lstSend:
                if fid == 0:
                    for oClientSocket in self.m_ClientSocketInfo.values():
                        iLen = len(sMsg)
                        sBuff = struct.pack("i", iLen) + sMsg
                        oClientSocket.m_Socket.send(sBuff)
                        print("send", sBuff)
                else:
                    oClientSocket = self.m_ClientSocketInfo.get(fid, None)
                    if not oClientSocket:
                        continue
                    iLen = len(sMsg)
                    sBuff = struct.pack("i", iLen) + sMsg
                    oClientSocket.m_Socket.send(sBuff)
                    print("send", sBuff)

    def EpollLoop(self, oEpoll):
        while True:
            events = oEpoll.poll(1)
            print("events")
            for fid, event in events:
                #新连接
                if fid == self.m_ServerSocket.fileno():
                    oNewConnect, address = self.m_ServerSocket.accept()
                    oNewConnect.setblocking(0)
                    oEpoll.register(oNewConnect.fileno(), select.EPOLLIN)
                    oClientSocket = CClientSocket(oNewConnect)
                    self.m_ClientSocketInfo[oNewConnect.fileno()] = oClientSocket
                    print("new connect")
                elif event & select.EPOLLIN:
                    oClientSocket = self.m_ClientSocketInfo[fid]
                    oClientSocket.RecvMsg()


def Init():
    global g_NetWorkManager
    g_NetWorkManager = CNetWorkManager()

def GetNetWorkManager():
    global g_NetWorkManager
    return g_NetWorkManager

def SendMsg(socketid, sMsg):
    GetNetWorkManager().SendMsg(socketid, sMsg)

def SendAll(sMsg):
    GetNetWorkManager().SendAll(sMsg)